package com.dxy.lp.controller;

import com.alibaba.fastjson.JSON;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Description 模拟客户端（向Nacos拉取配置的应用）
 * @Author dangxianyue
 * @Date 2024/3/19 16:24
 */
public class Client {

    // 假设配置有两个dataId
    private static final String exampleDataIds = "cipos-work,cipos-commons";

    // 模拟客户端本地缓存dataId和对应的MD5（dataId是已经固定在配置文件中的）
    private static Map<String, String> md5Map = new ConcurrentHashMap<>();

    // 轮询线程池（长轮询解释，长：长连接，轮询：客户端不断轮询请求）
    private static ScheduledExecutorService longPollingExecutor = Executors.newSingleThreadScheduledExecutor();

    private static String buildParam() {
        final String[] split = exampleDataIds.split(",");
        final List<String> pairList = Arrays.stream(split).map(Client::pair).collect(Collectors.toList());
        return String.join(ServerController.PAIR_SEPARATOR, pairList);
    }

    private static String pair(String dataId) {
        String md5 = md5Map.get(dataId);
        if (md5 == null) {
            md5 = "123456";
        }
        return dataId + ServerController.WORD_SEPARATOR + md5;
    }

    private static void handleConfigInfo(String content) {
        if (content != null && content.length() > 0) {
            System.out.println("获取到最新配置信息：" + content);
            final List<ServerController.ConfigInfo> configList = JSON.parseArray(content, ServerController.ConfigInfo.class);
            // TODO doing something ...
            // 可以设置到本地缓存或者Spring Environment中
            for (ServerController.ConfigInfo configInfo : configList) {
                md5Map.put(configInfo.getDataId(), configInfo.getMd5());
            }
        }
    }

    // 拉取配置任务
    static class PullConfigTask implements Runnable {

        @Override
        public void run() {
            try {
                // 参数
                final String param = buildParam();

                // 创建URL对象
                URL url = new URL("http://localhost:8080/pullConfigByLongPolling?data=" + param);
                System.out.println("URL: " + url.toString());

                // 打开连接
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();

                // 设置连接超时时间为 5 秒
                connection.setConnectTimeout(5000);

                // 设置读取超时时间为 30 秒
                connection.setReadTimeout(ServerController.LONG_POLLING_TIMEOUT);

                // 设置请求方法
                connection.setRequestMethod("GET");

                // 可选：设置请求头
                connection.setRequestProperty("User-Agent", "Mozilla/5.0");

                // 发送请求
                int responseCode = connection.getResponseCode();
                System.out.println("Response Code: " + responseCode);

                // 读取响应内容
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                String line;
                StringBuilder response = new StringBuilder();
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
                reader.close();

                // 输出响应内容
                System.out.println("Response Body: " + response.toString());

                // 业务处理
                handleConfigInfo(response.toString());

                // 关闭连接
                connection.disconnect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        // 延迟500ms后开始执行，在上一个任务完成间隔1000ms轮询执行
        longPollingExecutor.scheduleWithFixedDelay(new PullConfigTask(), 500, 1000, TimeUnit.MILLISECONDS);
    }
}
